﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using XXF.BaseService.ServiceCenter.Service.Provider;

namespace XXF.BaseService.ServiceCenter.Service.Performance
{
    public abstract class BasePerformance
    {
        public int ErrorCount { get; set; }
        public int ConnectionCount { get; set; }
        public int VisitCount { get; set; }
        public int ProcessThreadCount { get; set; }
        public double ProcessCpuPercent { get; set; }
        public double MemorySize { get; set; }

        protected ServiceContext _context;
        protected PerformanceCounter _processcpu;

        public BasePerformance(ServiceContext context)
        {
            _context = context;
            _processcpu = new PerformanceCounter("Process", "% Processor Time", GetProcessInstanceName(System.Diagnostics.Process.GetCurrentProcess().Id));
            if (!AppDomain.CurrentDomain.IsDefaultAppDomain())
            {
                AppDomain.MonitoringIsEnabled = true;
            }
        }

        public void Collect()
        {
            CollectPerformance(() => {
                ErrorCount = _context.Server.ServerVisitor.ServerVisitor.ErrorCount;
            }, () => {
                ErrorCount = -1;
            });

            CollectPerformance(() =>
            {
                ConnectionCount = _context.Server.ServerVisitor.ServerVisitor.ConnectionCount;
            }, () =>
            {
                ConnectionCount = -1;
            });
            CollectPerformance(() =>
            {
                VisitCount = _context.Server.ServerVisitor.ServerVisitor.VisitCount;
            }, () =>
            {
                VisitCount = -1;
            });
            CollectPerformance(() =>
            {
                ProcessThreadCount = System.Diagnostics.Process.GetCurrentProcess().Threads.Count;
            }, () =>
            {
                ProcessThreadCount = -1;
            });
            CollectPerformance(() =>
            {
                ProcessCpuPercent = _processcpu.NextValue();
            }, () =>
            {
                ProcessCpuPercent = -1;
            });
            CollectPerformance(() =>
            {
                if (AppDomain.CurrentDomain.IsDefaultAppDomain())
                {
                    MemorySize = (double)System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / 1024 / 1024;
                }
                else
                {

                    MemorySize = (double)AppDomain.CurrentDomain.MonitoringSurvivedMemorySize / 1024 / 1024;
                }
            }, () =>
            {
                MemorySize = -1;
            });
        }

        protected void CollectPerformance(Action action, Action actionexception)
        {
            try
            {
                action.Invoke();
            }
            catch (Exception exp)
            {
                try
                {
                    actionexception.Invoke();
                }
                catch { }
            }
        }

        private string GetProcessInstanceName(int pid)
        {
            var category = new PerformanceCounterCategory("Process");

            var instances = category.GetInstanceNames();
            foreach (var instance in instances)
            {

                using (var counter = new PerformanceCounter(category.CategoryName,
                     "ID Process", instance, true))
                {
                    int val = (int)counter.RawValue;
                    if (val == pid)
                    {
                        return instance;
                    }
                }
            }
            return null;
        }
    }
}
